home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_hylafax.idb / usr / freeware / sbin / faxcron.z / faxcron
Encoding:
Text File  |  1999-07-16  |  11.9 KB  |  467 lines

  1. #! /bin/sh
  2. #    $Id: faxcron.sh.in,v 1.41 1998/02/07 14:16:38 guru Rel $
  3. #
  4. # HylaFAX Facsimile Software
  5. #
  6. # Copyright (c) 1993-1996 Sam Leffler
  7. # Copyright (c) 1993-1996 Silicon Graphics, Inc.
  8. # HylaFAX is a trademark of Silicon Graphics
  9. # Permission to use, copy, modify, distribute, and sell this software and 
  10. # its documentation for any purpose is hereby granted without fee, provided
  11. # that (i) the above copyright notices and this permission notice appear in
  12. # all copies of the software and related documentation, and (ii) the names of
  13. # Sam Leffler and Silicon Graphics may not be used in any advertising or
  14. # publicity relating to the software without the specific, prior written
  15. # permission of Sam Leffler and Silicon Graphics.
  16. # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  17. # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  18. # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  19. # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20. # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21. # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22. # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23. # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24. # OF THIS SOFTWARE.
  25. #
  26.  
  27. #
  28. # Script to run periodically from cron:
  29. #
  30. # 0. Print transmit and receive statistics.
  31. # 1. Purge info directory of old remote machine capabilities.
  32. # 2. Purge old session logs from the log directory.
  33. # 3. Purge old files in the received facsimile queue.
  34. # 4. Notify about sites that currently have jobs rejected.
  35. #
  36.  
  37. AGEINFO=30            # purge remote info after 30 days inactivity
  38. AGELOG=30            # keep log info for last 30 days
  39. AGERCV=7            # purge received facsimile after 2 days
  40. AGETMP=1            # purge orphaned temp files after 1 day
  41. FAXUSER=fax            # owner of log files
  42. LOGMODE=0644            # mode for log files
  43. XFERLOG=etc/xferlog        # HylaFAX xferlog file location
  44. LAST=etc/lastrun        # file where time+date of last run recorded
  45.  
  46. cd /usr/freeware/var/spool/fax            # NB: everything below assumes this
  47.  
  48. test -f etc/setup.cache || {
  49.     SPOOL=`pwd`
  50.     cat<<EOF
  51.  
  52. FATAL ERROR: $SPOOL/etc/setup.cache is missing!
  53.  
  54. The file $SPOOL/etc/setup.cache is not present.  This
  55. probably means the machine has not been setup using the faxsetup(1M)
  56. command.  Read the documentation on setting up HylaFAX before you
  57. startup a server system.
  58.  
  59. EOF
  60.     exit 1
  61. }
  62. . etc/setup.cache
  63.  
  64. RM="$RM -f"
  65. TEE=tee
  66. UPDATE="date +'%D %H:%M' >$LAST"
  67.  
  68. JUNK=/tmp/faxjunk$$        # temp file used multiple times
  69. AWKTMP=/tmp/faxawk$$        # temp file for awk program
  70.  
  71. while [ x"$1" != x"" ] ; do
  72.     case $1 in
  73.     -n)        RM=":" TEE=":" CP=":" MV=":" CHOWN=":" CHMOD=":" UPDATE=":";;
  74.     -l)        shift; LASTRUN="$1";;
  75.     -info)  shift; AGEINFO="$1";;
  76.     -log)   shift; AGELOG="$1";;
  77.     -rcv)   shift; AGERCV="$1";;
  78.     -tmp)   shift; AGETMP="$1";;
  79.     -mode)  shift; LOGMODE="$1";;
  80.     -*)        echo "Usage: $0 [-n] [-l lastrun] [-info days] [-log days] [-rcv days] [-tmp days] [-mode logmode]"; exit 1;;
  81.     esac
  82.     shift
  83. done
  84.  
  85. trap "$RM \$AWKTMP \$JUNK; exit 1" 0 1 2 15
  86.  
  87.  
  88. test -z "$LASTRUN" && LASTRUN=`$CAT $LAST 2>/dev/null`
  89.  
  90. echo "Facsimile transmitted since $LASTRUN:"
  91. echo ""
  92. $SBIN/xferstats -since "$LASTRUN" 
  93. echo ""
  94.  
  95. echo "Facsimile transmitted since last week:"
  96. echo ""
  97. $SBIN/xferstats -age 7
  98. echo ""
  99.  
  100. echo "Facsimile received since $LASTRUN:"
  101. echo ""
  102. $SBIN/recvstats -since "$LASTRUN" 
  103. echo ""
  104.  
  105. echo "Facsimile received since last week:"
  106. echo ""
  107. $SBIN/recvstats -age 7
  108. echo ""
  109.  
  110. echo "Report failed calls and associated session logs:"
  111. $CAT>$AWKTMP<<'EOF'
  112. #
  113. # Sort array a[l..r]
  114. #
  115. function qsort(a, l, r) {
  116.     i = l;
  117.     k = r+1;
  118.     item = a[l];
  119.     for (;;) {
  120.     while (i < r) {
  121.             i++;
  122.         if (a[i] >= item)
  123.         break;
  124.         }
  125.     while (k > l) {
  126.             k--;
  127.         if (a[k] <= item)
  128.         break;
  129.         }
  130.         if (i >= k)
  131.         break;
  132.     t = a[i]; a[i] = a[k]; a[k] = t;
  133.     }
  134.     t = a[l]; a[l] = a[k]; a[k] = t;
  135.     if (k != 0 && l < k-1)
  136.     qsort(a, l, k-1);
  137.     if (k+1 < r)
  138.     qsort(a, k+1, r);
  139. }
  140.  
  141. function cleanup(s)
  142. {
  143.     gsub("\"", "", s);
  144.     gsub("^ +", "", s);
  145.     gsub(" +$", "", s);
  146.     return s;
  147. }
  148.  
  149. function setupToLower()
  150. {
  151.     upperRE = "[ABCDEFGHIJKLMNOPQRSTUVWXYZ]";
  152.     upper["A"] = "a"; upper["B"] = "b"; upper["C"] = "c";
  153.     upper["D"] = "d"; upper["E"] = "e"; upper["F"] = "f";
  154.     upper["G"] = "g"; upper["H"] = "h"; upper["I"] = "i";
  155.     upper["J"] = "j"; upper["K"] = "k"; upper["L"] = "l";
  156.     upper["M"] = "m"; upper["N"] = "n"; upper["O"] = "o";
  157.     upper["P"] = "p"; upper["Q"] = "q"; upper["R"] = "r";
  158.     upper["S"] = "s"; upper["T"] = "t"; upper["U"] = "u";
  159.     upper["V"] = "v"; upper["W"] = "w"; upper["X"] = "x";
  160.     upper["Y"] = "y"; upper["Z"] = "z";
  161. }
  162.  
  163. function toLower(s)
  164. {
  165.     if (match(s, upperRE) != 0) {
  166.     do {
  167.         c = substr(s, RSTART, 1);
  168.         gsub(c, upper[c], s);
  169.     } while (match(s, upperRE));
  170.     }
  171.     return s;
  172. }
  173.  
  174. #
  175. # Accumulate a statistics record.
  176. #
  177. function acct(dest, status, datetime, commid)
  178. {
  179.     split(datetime, a, " ");
  180.     split(a[1], b, "/");
  181.     t = b[3] b[1] b[2] a[2];
  182.     if (t < LASTt)
  183.     return;
  184.     status = cleanup(status);
  185.     if (length(status) > 11) {
  186.     msg = toLower(substr(status, 1, 11));
  187.     if (callFailed[msg])
  188.         return;
  189.     }
  190.     if (status != "") {
  191.     dest = cleanup(dest);
  192.     datetime = cleanup(datetime);
  193.     for (i = 0; i < nerrmsg; i++)
  194.         if (errmsg[i] == status)
  195.         break;
  196.     if (i == nerrmsg)
  197.         errmsg[nerrmsg++] = status;
  198.     if (errinfo[dest] == "")
  199.         errinfo[dest] = datetime "@" i "/" commid;
  200.     else
  201.         errinfo[dest] = errinfo[dest] "|" datetime "@" i "/" commid;
  202.     }
  203. }
  204.  
  205. function printOldTranscript(canon, datetime)
  206. {
  207.     gsub("[^0-9]", "", canon);
  208.     split(datetime, parts, " ");
  209.     split(parts[1], p, "/");
  210.     cmd = sprintf(TRANSCRIPT, canon, months[p[1]], p[2], parts[2]);
  211.     system(cmd);
  212. }
  213.  
  214. function printTranscript(commid)
  215. {
  216.     printf "\n    ---- Transcript of session follows ----\n\n"
  217.     comFile = "log/c" commid;
  218.     if ((getline <comFile) > 0) {
  219.     do {
  220.         if (index($0, "-- data") == 0)
  221.         print $0
  222.     } while ((getline <comFile) > 0);
  223.     close(comFile);
  224.     } else
  225.     print "No transcript available.";
  226. }
  227.  
  228. BEGIN        { FS="\t";
  229.           callFailed["busy signal"] = 1;
  230.           callFailed["unknown pro"] = 1;
  231.           callFailed["no carrier "] = 1;
  232.           callFailed["no local di"] = 1;
  233.           callFailed["no answer f"] = 1;
  234.           callFailed["job aborted"] = 1;
  235.           callFailed["invalid dia"] = 1;
  236.           callFailed["can not loc"] = 1;
  237.           months["01"] = "Jan"; months["02"] = "Feb";
  238.           months["03"] = "Mar"; months["04"] = "Apr";
  239.           months["05"] = "May"; months["06"] = "Jun";
  240.           months["07"] = "Jul"; months["08"] = "Aug";
  241.           months["09"] = "Sep"; months["10"] = "Oct";
  242.           months["11"] = "Nov"; months["12"] = "Dec";
  243.  
  244.           split(LASTRUN, a, " ");
  245.           split(a[1], b, "/");
  246.           LASTt = b[3] b[1] b[2] a[2];
  247.           setupToLower();
  248.         }
  249. $2 == "SEND" && NF == 9  { acct($4,  $9, $1, ""); }
  250. $2 == "SEND" && NF == 11 { acct($5, $11, $1, ""); }
  251. $2 == "SEND" && NF == 12 { acct($6, $12, $1, ""); }
  252. $2 == "SEND" && NF == 13 { acct($7, $13, $1, $3); }
  253. $2 == "SEND" && NF == 14 { acct($7, $14, $1, $3); }
  254. END        { nsorted = 0;
  255.           for (key in errinfo)
  256.               sorted[nsorted++] = key;
  257.           qsort(sorted, 0, nsorted-1);
  258.           for (k = 0; k < nsorted; k++) {
  259.               key = sorted[k];
  260.               n = split(errinfo[key], a, "|");
  261.               for (i = 1; i <= n; i++) {
  262.               if (split(a[i], b, "@") != 2)
  263.                   continue;
  264.               if (split(b[2], d, "/") != 2)
  265.                   continue;
  266.               printf "\n"
  267.               printf "To: %-16.16s  Date: %s\n", key, b[1]
  268.               printf "Error: %s\n\n", errmsg[d[1]]
  269.  
  270.               if (d[2] == "")
  271.                   printOldTranscript(key, b[1]);
  272.               else
  273.                   printTranscript(d[2]);
  274.               }
  275.           }
  276.         }
  277. EOF
  278. $AWK -f $AWKTMP -v LASTRUN="$LASTRUN" TRANSCRIPT="\
  279.     LOGFILE=log/%s;\
  280.     TMP=/tmp/faxlog\$\$;\
  281.     if [ -f \$LOGFILE ]; then\
  282.     $SED -n -e '/%s %s %s.*SESSION BEGIN/,/SESSION END/p' \$LOGFILE |\
  283.     $SED -e '/start.*timer/d'\
  284.          -e '/stop.*timer/d'\
  285.          -e '/-- data/d'\
  286.          -e 's/^/    /' >\$TMP;\
  287.     fi;\
  288.     if [ -s \$TMP ]; then\
  289.     $CAT \$TMP;\
  290.     else\
  291.     echo '    No transcript available.';\
  292.     fi;\
  293.     rm -f \$TMP\
  294.     " $XFERLOG
  295. echo ""
  296.  
  297. #
  298. # Collect phone numbers that haven't been called
  299. # in the last $AGEINFO days.  We use this to clean
  300. # up the info files.
  301. #
  302. find info -ctime +$AGEINFO -print >$JUNK
  303.  
  304. if [ -s $JUNK ]; then
  305. echo "Purge remote device capabilities older than $AGEINFO days:"
  306. INFOTMP=info/tmp$$
  307. for i in `$CAT $JUNK`; do
  308.     if $GREP '^&' $i >/dev/null 2>&1; then
  309.     echo "    $i (saving locked down values)"
  310.     $SED '/^[^&]/d' $i > $INFOTMP
  311.     $MV $INFOTMP $i; $CHOWN ${FAXUSER} $i; $CHMOD ${LOGMODE} $i
  312.     elif [ -f $i ]; then
  313.     echo "    $i"
  314.     $RM $i
  315.     fi
  316. done
  317. $RM $INFOTMP            # for -n option
  318. else 
  319.     echo "Nothing to purge in info directory."
  320. fi
  321. echo ""
  322.  
  323. find log -mtime +$AGELOG -print >$JUNK
  324. if [ -s $JUNK ]; then
  325.     echo "Purge session logs older than $AGELOG days:"
  326.     for i in `$CAT $JUNK`; do
  327.     echo "    Remove $i"
  328.     $RM $i
  329.     done
  330.     echo ""
  331. fi
  332.  
  333. echo "Truncate merged session logs older than $AGELOG days:"
  334.  
  335. $CAT>$AWKTMP<<'EOF'
  336. #
  337. # Setup date conversion data structures.
  338. #
  339. function setupDateTimeStuff()
  340. {
  341.     Months["Jan"] =  0; Months["Feb"] =  1; Months["Mar"] =  2;
  342.     Months["Apr"] =  3; Months["May"] =  4; Months["Jun"] =  5;
  343.     Months["Jul"] =  6; Months["Aug"] =  7; Months["Sep"] =  8;
  344.     Months["Oct"] =  9; Months["Nov"] = 10; Months["Dec"] = 11;
  345.  
  346.     daysInMonth[ 0] = 31; daysInMonth[ 1] = 28; daysInMonth[ 2] = 31;
  347.     daysInMonth[ 3] = 30; daysInMonth[ 4] = 31; daysInMonth[ 5] = 30;
  348.     daysInMonth[ 6] = 31; daysInMonth[ 7] = 31; daysInMonth[ 8] = 30;
  349.     daysInMonth[ 9] = 31; daysInMonth[10] = 30; daysInMonth[11] = 31;
  350.  
  351.     FULLDAY = 24 * 60 * 60;
  352. }
  353.  
  354. #
  355. # Convert MMM DD hh:mm:ss.ms to seconds.
  356. # NB: this does not deal with leap years.
  357. #
  358. function cvtTime(s)
  359. {
  360.     mon = Months[substr(s, 0, 3)];
  361.     yday = substr(s, 5, 2) - 1;
  362.     for (i = 0; i < mon; i++)
  363.     yday += daysInMonth[i];
  364.     s = substr(s, 7);
  365.     t = i = 0;
  366.     for (n = split(s, a, ":"); i++ < n; )
  367.     t = t*60 + a[i];
  368.     return yday*FULLDAY + t;
  369. }
  370.  
  371. BEGIN            { setupDateTimeStuff();
  372.               KEEP = cvtTime(TODAY) - AGE*FULLDAY;
  373.               lastRecord = "$"
  374.             }
  375.             { if (cvtTime($1 ":" $2 ":" $3) >= KEEP) {
  376.                   lastRecord = NR; exit
  377.               }
  378.             }
  379. END            { print lastRecord }
  380. EOF
  381. TODAY="`date +'%h %d %T'`"
  382.  
  383. for i in log/[0-9]*; do
  384.     if [ -f $i ]; then
  385.     START=`$AWK -F: -f $AWKTMP -v TODAY="$TODAY" -v AGE=$AGELOG $i` 2>/dev/null
  386.     if [ "$START" != 1 ]; then
  387.         $SED 1,${START}d $i >$JUNK
  388.         if [ -s $JUNK ]; then
  389.         $MV $JUNK $i; $CHOWN ${FAXUSER} $i; $CHMOD ${LOGMODE} $i
  390.         ls -ls $i
  391.         else
  392.         echo "    Remove empty $i"
  393.         $RM $i
  394.         fi
  395.     fi
  396.     fi
  397. done
  398. echo ""
  399.  
  400. #
  401. # Purge old stuff from the receive queue.
  402. #
  403. find recvq -mtime +$AGERCV -print >$JUNK
  404. if [ -s $JUNK ]; then
  405.     echo "Purge received facsimile older than $AGERCV days:"
  406.     (for i in `$CAT $JUNK`; do
  407.     $SBIN/faxinfo $i
  408.     $RM $i >/dev/null 2>&1
  409.     done) | $AWK -F: '
  410. /recvq.*/    { file=$1; }
  411. /Sender/    { sender = $2; }
  412. /Pages/        { pages = $2; }
  413. /Quality/    { quality = $2; }
  414. /Received/    { date = $2;
  415.           for (i = 3; i <= NF; i++)
  416.               date = date ":" $i;
  417.           printf "    %-16.16s %21.21s %2d %8s%s\n", \
  418.             file, sender, pages, quality, date;
  419.         }
  420. '
  421. else
  422.     echo "Nothing to purge in receive queue."
  423. fi
  424. echo ""
  425.  
  426. #
  427. # Purge old stuff from the temp directory.
  428. #
  429. find tmp -type f -mtime +$AGETMP -print >$JUNK
  430. if [ -s $JUNK ]; then
  431.     echo "Purge tmp files older than $AGETMP days:"
  432.     for i in `$CAT $JUNK`; do
  433.       if [ -f $i ]; then
  434.     echo "    Remove $i"
  435.     $RM $i
  436.       fi
  437.     done
  438. else
  439.     echo "Nothing to purge in the tmp directory."
  440. fi
  441. echo ""
  442.  
  443. #
  444. # Note destinations whose jobs are currently being rejected.
  445. #
  446. find info cinfo -newer $LAST -print 2>/dev/null >$JUNK
  447. if [ -s $JUNK ]; then
  448.     echo "Destinations being rejected (added since $LASTRUN):"
  449.     $GREP "^rejectNotice:" `$CAT $JUNK` | $AWK -F: '
  450.         { reason = $3;
  451.           for (i = 4; i <= NF; i++)
  452.             reason = reason ":" $i;
  453.           sub("^[ ]*", "", reason);
  454.           if (reason != "") {
  455.               sub(".*/", "", $1);
  456.               printf "Rejecting jobs to +%s because \"%s\".\n", \
  457.                 $1, reason;
  458.           }
  459.         }
  460. '
  461. fi
  462.  
  463. $RM $LAST; eval $UPDATE
  464.